﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Navigation;
using FirstFloor.Documents;
using FirstFloor.Documents.Controls;
using FirstFloor.Documents.Controls.Behaviors;
using FirstFloor.Documents.IO.DotNetZip;

namespace SampleBrowser.Views
{
    public partial class SampleSinglePage
        : Page, ITextContainer
    {
        private VirtualizingPageCollection pages;
        private PageContextBase currentPage;
        private Point? dragMousePos;
        private Point dragMouseOffset;

        public SampleSinglePage()
        {
            InitializeComponent();

            // enable link navigation
            new NavigationBehavior() { TextContainer = this }
                .Attach(this.PageViewer);

            this.Loaded += (o, e) => {
                // create a page collection
                this.pages = this.DataSource.CreatePageCollection();

                this.DataSource.PackageReader = new DotNetZipPackageReader(new Uri("Assets/Documents/TestDocument.xps", UriKind.Relative));
            };
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);

            // properly clears the datasource and closes the package reader
            this.DataSource.PackageReader = null;
        }


        private void DataSource_LoadError(object sender, ErrorEventArgs e)
        {
            new ErrorWindow(e.Error).Show();
        }

        private void Navigator_PageIndexChanged(object sender, EventArgs e)
        {
            if (this.currentPage != null) {
                // unload current page
                this.currentPage.IsInUse = false;
            }

            // get the page from the collection
            this.currentPage = pages.ElementAtOrDefault(this.Navigator.PageIndex);
            if (this.currentPage != null) {
                // make sure the page is loaded
                this.currentPage.IsInUse = true;
            }

            // assign page to page viewer
            this.PageViewer.DataContext = this.currentPage;
        }

        #region Panning and Zooming
        private void StopCurrentMouseOperation()
        {
            this.PageViewerBorder.ReleaseMouseCapture();
            this.dragMousePos = null;
        }

        private void PageViewerBorder_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.dragMousePos = e.GetPosition(this.ScrollViewer);
            this.dragMouseOffset = new Point(this.ScrollViewer.HorizontalOffset, this.ScrollViewer.VerticalOffset);
            this.PageViewerBorder.CaptureMouse();
        }

        private void PageViewerBorder_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.dragMousePos != null) {
                var position = e.GetPosition(this.ScrollViewer);

                this.ScrollViewer.ScrollToHorizontalOffset(this.dragMouseOffset.X + this.dragMousePos.Value.X - position.X);
                this.ScrollViewer.ScrollToVerticalOffset(this.dragMouseOffset.Y + this.dragMousePos.Value.Y - position.Y);
            }
        }

        private void PageViewerBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            StopCurrentMouseOperation();
        }

        private void PageViewerBorder_LostMouseCapture(object sender, MouseEventArgs e)
        {
            StopCurrentMouseOperation();
        }

        private void PageViewerBorder_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            var scale = this.PageViewer.Scale ?? 1;

            if (e.Delta > 0) {
                this.PageViewer.Scale = Math.Min(10, scale * 1.1);
            }
            else {
                this.PageViewer.Scale = Math.Max(.02, scale / 1.1);
            }

            e.Handled = true;       // prevent scrollviewer from using mouse wheel
        }
        #endregion

        #region ITextContainer Members

        public void BringIntoView(TextPointer position)
        {
            this.Navigator.PageIndex = position.PageNumber - 1;
        }

        public void BringIntoView(LinkTarget linkTarget)
        {
            this.Navigator.PageIndex = linkTarget.Page.PageNumber - 1;
        }

        public string GetText(ref TextPointer position1, ref TextPointer position2)
        {
            throw new NotImplementedException();
        }

        public void OnAnnotationServiceChanged()
        {
            throw new NotImplementedException();
        }

        public int PageNumber
        {
            get
            {
                return this.Navigator.PageIndex + 1;
            }
            set
            {
                this.Navigator.PageIndex = value - 1;
            }
        }

        public TextSelection Selection
        {
            get { return null; }
        }

        #endregion

    }
}
